package edu.towson.cis.cosc442.project2.vendingmachine;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class VendingMachineTest {
    VendingMachine vend1;
    VendingMachineItem item;

    @Rule
    public ExpectedException exception = ExpectedException.none();

    //Setup method
    @Before
    public void setUp() {
	vend1 = new VendingMachine();
	item = new VendingMachineItem("Godiva Chocolate", 4.00);
    }

    // Tests for single entry
    @Test
    public void testAddItem() {
	vend1.addItem(item, VendingMachine.B_CODE);
	assertEquals(item, vend1.getItem(VendingMachine.B_CODE));
    }

    // Tests for duplicate entries
    @Test
    public void testAddItem2() {
	exception.expectMessage(vend1.ALREADY_OCCUPIED_MESSAGE);
	vend1.addItem(item, VendingMachine.A_CODE);
	vend1.addItem(item, VendingMachine.A_CODE);
    }

    // Tests for incorrect value entry
    @Test
    public void testAddItem3() {
	exception.expectMessage(VendingMachine.INVALID_CODE_MESSAGE);
	vend1.addItem(item, "Z");
    }

    // Tests for item equal to null
    @Test
    public void testAddItem4() {
	assertNull(vend1.getItem(VendingMachine.A_CODE));
    }

    // Tests for single entry
    @Test
    public void testAddItem5() {
	vend1.addItem(item, VendingMachine.C_CODE);
	assertEquals(item, vend1.getItem(VendingMachine.C_CODE));
    }

    // Tests for single entry
    @Test
    public void testAddItem6() {
	vend1.addItem(item, VendingMachine.D_CODE);
	assertEquals(item, vend1.getItem(VendingMachine.D_CODE));
    }

    // Tests for removal of entry
    @Test
    public void testRemoveItem() {
	vend1.addItem(item, VendingMachine.B_CODE);
	vend1.removeItem(VendingMachine.B_CODE);
	assertEquals(null, vend1.getItem(VendingMachine.B_CODE));
    }

    // Tests for removal of entry from an empty list
    @Test
    public void testRemoveItem3() {
	exception.expectMessage(vend1.IS_EMPTY_MESSAGE);
	vend1.removeItem(VendingMachine.B_CODE);
    }

    // Tests for negative entry of money
    @Test
    public void testInsertMoney() {
	exception.expectMessage(vend1.INVALID_AMOUNT_MESSAGE);
	vend1.insertMoney(-3.33);
    }

    // Tests for 0 entry of money
    @Test
    public void testInsertMoney2() {
	vend1.insertMoney(0);
	assertEquals(0, vend1.getBalance(), 0.001);
    }

    // Tests for above 0 entry of money
    @Test
    public void testGetBalance() {
	vend1.insertMoney(3.33);
	assertEquals(3.33, vend1.getBalance(), 0.001);
    }

    // Tests through the purchasing process of inserting adding and purchasing
    @Test
    public void testMakePurchase() {
	vend1.insertMoney(4.50);
	vend1.addItem(item, VendingMachine.B_CODE);
	vend1.makePurchase(VendingMachine.B_CODE);
	assertEquals(.50, vend1.getBalance(), 0.001);
    }

    // Tests for correct return change value
    @Test
    public void testReturnChange() {
	vend1.insertMoney(4.50);
	assertEquals(4.50, vend1.returnChange(), 0.001);
    }
    
    //Tear down method
    @After
    public void tearDown() {
	vend1 = null;
	item = null;
    }
}
